using System;
using System.Configuration;
using Common.Core;
using Microsoft.Practices.ObjectBuilder2;
using Microsoft.Practices.Unity;
using Microsoft.Practices.Unity.Configuration;

namespace Common.Unity.Configuration
{
	public class TypeInstanceElement : InjectionParameterValueElement, IDependencyResolverPolicy
	{
		[ConfigurationProperty( ElementTypeName, DefaultValue = null, IsRequired = false, IsKey = false )]
		public new string ElementType
		{
			get { return (string)this[ElementTypeName]; }
			set { this[ElementTypeName] = value; }
		}	const string ElementTypeName = "elementType";

		[ConfigurationProperty( TypeName, DefaultValue = null, IsRequired = true, IsKey = false )]
		public UnityTypeInstanceElement Instance
		{
			get { return (UnityTypeInstanceElement)this[TypeName]; }
			set { this[TypeName] = value; }
		}	const string TypeName = "instance";

		IUnityContainer Container
		{
			get { return container ?? ( container = ResolveContainer() ); }
		}	IUnityContainer container;

		static IUnityContainer ResolveContainer()
		{
			IUnityContainer result = ThreadLocalStorage.Peek<IUnityContainer>();
			if ( result != null )
			{
				return result;
			}
			throw new InvalidOperationException( "An instance of an IUnityContainer could not be found in the current thread." );
		}

		public override InjectionParameterValue CreateParameterValue(Type targetType)
		{
			Instance.TypeResolver = TypeResolver;
			Instance.TypeName = !string.IsNullOrEmpty( Instance.TypeName ) ? Instance.TypeName : targetType.AssemblyQualifiedName;
			Instance.Name = Guid.NewGuid().ToString();
			Instance.Configure( Container );
			return new DependencyResolverParameterValue( this, targetType );
		}

		object IDependencyResolverPolicy.Resolve( IBuilderContext context )
		{
			IBuilderContext itemContext = context.CloneForNewBuild( new NamedTypeBuildKey( Instance.Type, Instance.Name ), null );
			object result = itemContext.Strategies.ExecuteBuildUp( itemContext );
			return result;
		}
	}
}